import 'package:flutter/material.dart';
import 'dart:async';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'dart:io';

class DownloadUtil {
  final String id;
  final List filesList;

  List<_TaskInfo> _tasks;
  List<_ItemHolder> _items;
  String _saveDir;

  DownloadUtil({Key key, this.filesList, this.id});

  void dispose() {
    FlutterDownloader.registerCallback(null);
  }

  Future<Null> init() async {
    /// 注册事件
    FlutterDownloader.registerCallback((id, status, progress) {
      print('Download task ($id) is in status ($status) and process ($progress)');
      final task = _tasks.firstWhere((task) => task.taskId == id);
      task?.status = status;
      task?.progress = progress;
    });

    final tasks = await FlutterDownloader.loadTasks();

    int count = 0;
    _tasks = [];
    _items = [];

    _tasks.addAll(filesList
        .map((file) => _TaskInfo(name: file['name'], url: file['url'])));

    for (int i = count; i < _tasks.length; i++) {
      _items.add(_ItemHolder(name: _tasks[i].name, task: _tasks[i]));
      count++;
    }

    tasks?.forEach((task) {
      for (_TaskInfo info in _tasks) {
        if (info.url == task.url) {
          info.taskId = task.taskId;
          info.status = task.status;
          info.progress = task.progress;
        }
      }
    });

    _saveDir = await _findLocalPath();
    final savedDir = Directory(_saveDir);
    bool hasExisted = await savedDir.exists();
    if (!hasExisted) {
      savedDir.create();
    }
  }

  Future<String> _findLocalPath() async {
    final directory = await getApplicationDocumentsDirectory();
    return directory.path + '/player_material/$id';
  }

  void _requestDownload(_TaskInfo task) async {
    task.taskId = await FlutterDownloader.enqueue(
      url: task.url,
      headers: {},
      savedDir: _saveDir,
      showNotification: true,
      openFileFromNotification: false
    );
  }

  void _retryDownload(_TaskInfo task) async {
    String newTaskId = await FlutterDownloader.retry(taskId: task.taskId);
    task.taskId = newTaskId;
  }
}


class _TaskInfo {
  final String name;
  final String url;

  String taskId;
  int progress = 0;
  DownloadTaskStatus status = DownloadTaskStatus.undefined;

  _TaskInfo({this.name, this.url});
}

class _ItemHolder {
  final String name;
  final _TaskInfo task;

  _ItemHolder({this.name, this.task});
}